﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using UEditor.Code;
using System.IO;

namespace UEditor.Controllers
{
    public class UEController : Controller
    {

        public ActionResult Index()
        {
            Config myconfig = new Config();
            UploadConfig uploadConfig = new UploadConfig();
            switch (Request["action"])
            {
                case "config":
                    config();
                    break;
                case "uploadimage":
                    uploadConfig= new UploadConfig()
                    {
                        AllowExtensions = myconfig.GetStringList("imageAllowFiles"),
                        PathFormat = myconfig.GetString("imagePathFormat"),
                        SizeLimit = myconfig.GetInt("imageMaxSize"),
                        UploadFieldName = myconfig.GetString("imageFieldName")
                    };
                    this.WriteJson(WriteUploadJson(uploadimage(uploadConfig)));
                    break;
                case "uploadscrawl":
                    uploadConfig = new UploadConfig()
                    {
                        AllowExtensions = new string[] { ".png" },
                        PathFormat = myconfig.GetString("scrawlPathFormat"),
                        SizeLimit = myconfig.GetInt("scrawlMaxSize"),
                        UploadFieldName = myconfig.GetString("scrawlFieldName"),
                        Base64 = true,
                        Base64Filename = "scrawl.png"
                    };
                    this.WriteJson(WriteUploadJson(uploadimage(uploadConfig)));
                    break;
                case "uploadvideo":
                    uploadConfig = new UploadConfig()
                    {
                        AllowExtensions = myconfig.GetStringList("videoAllowFiles"),
                        PathFormat = myconfig.GetString("videoPathFormat"),
                        SizeLimit = myconfig.GetInt("videoMaxSize"),
                        UploadFieldName = myconfig.GetString("videoFieldName")
                    };
                    this.WriteJson(WriteUploadJson(uploadimage(uploadConfig)));
                    break;
                case "uploadfile":
                    uploadConfig = new UploadConfig()
                    {
                        AllowExtensions = myconfig.GetStringList("fileAllowFiles"),
                        PathFormat = myconfig.GetString("filePathFormat"),
                        SizeLimit = myconfig.GetInt("fileMaxSize"),
                        UploadFieldName = myconfig.GetString("fileFieldName")
                    };
                    this.WriteJson(WriteUploadJson(uploadimage(uploadConfig)));
                    break;
                case "listimage":
                    this.WriteJson(new ListFileManager(myconfig.GetString("imageManagerListPath"), myconfig.GetStringList("imageManagerAllowFiles")).Result(Request["start"], Request["size"], myconfig));
                    break;
                case "listfile":
                    this.WriteJson(new ListFileManager(myconfig.GetString("fileManagerListPath"), myconfig.GetStringList("fileManagerAllowFiles")).Result(Request["start"], Request["size"], myconfig));
                    
                    break;
                case "catchimage":
                    string[] Sources;
                    Crawler[] Crawlers;
                    Sources = Request.Form.GetValues("source[]");
                    if (Sources == null || Sources.Length == 0)
                    {
                        WriteJson(new
                        {
                            state = "参数错误：没有指定抓取源"
                        });
                    }
                    Crawlers = Sources.Select(x => new Crawler(x,Server).Fetch()).ToArray();
                    WriteJson(new
                    {
                        state = "SUCCESS",
                        list = Crawlers.Select(x => new
                        {
                            state = x.State,
                            source = x.SourceUrl,
                            url = x.ServerUrl
                        })
                    });
                    break;
                default:
                    WriteJson(new
                    {
                        state = "action 参数为空或者 action 不被支持。"
                    });
                    break;
            }
            return new EmptyResult();
        }

        public void config()
        {
            this.WriteJson(new Config().Items);
        }

        #region 上传
        public UploadResult uploadimage(UploadConfig uploadConfig)
        {
            byte[] uploadFileBytes = null;
            string uploadFileName = null;

            UploadResult Result = new UploadResult() { state = UploadState.Unknown };


            if (uploadConfig.Base64)
            {
                uploadFileName = uploadConfig.Base64Filename;
                uploadFileBytes = Convert.FromBase64String(Request[uploadConfig.UploadFieldName]);
            }
            else
            {
                var file = Request.Files[uploadConfig.UploadFieldName];
                uploadFileName = file.FileName;

                if (!CheckFileType(uploadFileName, uploadConfig))
                {
                    Result.state = UploadState.TypeNotAllow;
                    return Result;
                }
                if (!CheckFileSize(file.ContentLength, uploadConfig))
                {
                    Result.state = UploadState.SizeLimitExceed;
                    return Result;
                }

                uploadFileBytes = new byte[file.ContentLength];
                try
                {
                    file.InputStream.Read(uploadFileBytes, 0, file.ContentLength);
                }
                catch (Exception)
                {
                    Result.state = UploadState.NetworkError;
                    return Result;
                }
            }

            Result.original = uploadFileName;

            var savePath = new PathFormatter().Format(uploadFileName, uploadConfig.PathFormat);
            var localPath = Server.MapPath(savePath);
            try
            {
                if (!Directory.Exists(Path.GetDirectoryName(localPath)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(localPath));
                }
                System.IO.File.WriteAllBytes(localPath, uploadFileBytes);
                Result.url = savePath;
                Result.state = UploadState.Success;
            }
            catch (Exception e)
            {
                Result.state = UploadState.FileAccessError;
                Result.error = e.Message;
            }
            return Result;
        }

        public object WriteUploadJson(UploadResult result)
        {
            return new
            {
                state = GetStateMessage(result.state),
                url=result.url,
                original=result.original,
                title=result.original
            };
        }

        private string GetStateMessage(UploadState state)
        {
            switch (state)
            {
                case UploadState.Success:
                    return "SUCCESS";
                case UploadState.FileAccessError:
                    return "文件访问出错，请检查写入权限";
                case UploadState.SizeLimitExceed:
                    return "文件大小超出服务器限制";
                case UploadState.TypeNotAllow:
                    return "不允许的文件格式";
                case UploadState.NetworkError:
                    return "网络错误";
            }
            return "未知错误";
        }

        private bool CheckFileType(string filename, UploadConfig uploadConfig)
        {
            var fileExtension = Path.GetExtension(filename).ToLower();
            return uploadConfig.AllowExtensions.Select(x => x.ToLower()).Contains(fileExtension);
        }

        private bool CheckFileSize(int size, UploadConfig uploadConfig)
        {
            return size < uploadConfig.SizeLimit;
        }
        #endregion

        private void WriteJson(object response)
        {
            string jsonpCallback = Request["callback"],
            json = JsonConvert.SerializeObject(response);
            if (String.IsNullOrWhiteSpace(jsonpCallback))
            {
                Response.AddHeader("Content-Type", "text/plain");
                Response.Write(json);
            }
            else
            {
                Response.AddHeader("Content-Type", "application/javascript");
                Response.Write(String.Format("{0}({1});", jsonpCallback, json));
            }
            Response.End();
        }

    }
}